/**
 * 
 */
package com.fengwk.support.util;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.fengwk.support.exception.BaseException;

/**
 * 工具类:操作字符串内容
 */
public final class StringUtils {
	
	private static final int TRIM_HTML_ATTR_COMMEND = 0;
    private static final int TRIM_HTML_ATTR_WITH_EXCLUDE_COMMEND = 1;
    private static final int TRIM_HTML_ATTR_WITH_INCLUDE_COMMEND = 2;

    public static final String UNDERLINE = "_";
    
	private StringUtils() {
		throw new BaseException("can not instance " + getClass());
	}

	/**
	 * 字符串为空判断
	 * 
	 * <pre>
     * StringUtils.isBlank(null)      = true
     * StringUtils.isBlank("")        = true
     * StringUtils.isBlank(" ")       = true
     * StringUtils.isBlank("bob")     = false
     * StringUtils.isBlank("  bob  ") = false
     * </pre>
	 * @param str
	 * @return
	 */
	public static boolean isBlank(String str) {
		int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(str.charAt(i)) == false) {
                return false;
            }
        }
        return true;
	}
	
	/**
	 * 字符串非空判断
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNotBlank(String str) {
		return !isBlank(str);
	}
	
	/**
	 * 字符串空白判断
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isEmpty(String str) {
		return str == null || str.length() == 0;
	}

	/**
	 * 字符串非空白判断
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNotEmpty(String str) {
		return !isEmpty(str);
	}
	
	/**
	 * substring方法,解决内存溢出
	 * 
	 * @param str
	 * @param beginIndex
	 * @return
	 */
	public static String substring(String str, int beginIndex) {
		return new String(str.substring(beginIndex));
	}
	
	/**
	 * substring方法,解决内存溢出
	 * 
	 * @param str
	 * @param beginIndex
	 * @return
	 */
	public static String substring(String str, int beginIndex, int endIndex) {
		return new String(str.substring(beginIndex, endIndex));
	}
    
    /**
     * 生成随机数字符串
     * 
     * @param len 生成随机字串的长度
     * @return 生成的随机数字符串
     */
    public static String createRandomNumber(int len) {
    	if(len <= 0) {
    		return "";
    	}
    	StringBuffer randomNumber = new StringBuffer();
    	for(int i=0;i<len;i++){
			int num=(int)(Math.random()*10);
			randomNumber.append(num);
		}
    	return randomNumber.toString();
    }
    
    /**
     * 去后缀
     * 
     * @param src
     * @param suffix
     * @return
     */
    public static String trimSuffix(String src, String suffix) {
    	return src.replaceAll(suffix + "$", "");
    }
    
    /**
     * 去前缀
     * 
     * @param src
     * @param prefix
     * @return
     */
    public static String trimPrefix(String src, String prefix) {
    	return src.replaceAll("^" + prefix, "");
    }
    
    /**
     * 包含str
     * 
     * @param str 检测子串
     * @param strArray 子串数组
     * @return
     */
    public static boolean contains(String str, String[] strArray, boolean ignoreCase) {
    	if(StringUtils.isEmpty(str) || ArrayUtils.isBlank(strArray)) {
    		return false;
    	}
    	for(String buff: strArray) {
    		if(ignoreCase) {
    			if(str.equalsIgnoreCase(buff)) {
        			return true;
        		}
    		} else {
    			if(str.equals(buff)) {
        			return true;
        		}
    		}
    	}
		return false;
    }

    /**
     * 包含str
     * 
     * @param str
     * @param strCollection
     * @return
     */
    public static boolean contains(String str, Collection<String> strCollection, boolean ignoreCase) {
    	if(CollectionUtils.isBlank(strCollection)) {
    		return false;
    	}
    	String[] strs = new String[strCollection.size()];
    	strs = strCollection.toArray(strs);
    	return contains(str, strs, ignoreCase);
    }
    
    /**
     * 正则包含匹配
     * 
     * @param regex
     * @param collection
     * @return
     */
    public static boolean containsAll(String regex, String[] strArray) {
    	if(isEmpty(regex) || ArrayUtils.isBlank(strArray)) {
    		return false;
    	}
    	for(String buff: strArray) {
    		if(RegexUtils.regex(buff, regex) != null) {
    			return true;
    		}
    	}
		return false;
    }
    
    /**
     * 正则包含匹配
     * 
     * @param regex
     * @param strCollection
     * @return
     */
    public static boolean containsAll(String regex, Collection<String> strCollection) {
    	if(isEmpty(regex) || CollectionUtils.isBlank(strCollection)) {
    		return false;
    	}
    	for(String buff: strCollection) {
    		if(RegexUtils.regex(buff, regex) != null) {
    			return true;
    		}
    	}
		return false;
    }
    
    /**
     * 字符集转换
     * 
     * @param str
     * @return
     * @throws UnsupportedEncodingException 
     */
    public static String convertCharset(String str, String srcCharset, String tarCharset) throws UnsupportedEncodingException {
    	return new String(str.getBytes(srcCharset), tarCharset);
    }
    
    /**
     * 获取html判断中指定标签的指定属性集
     * 
     * @param html
     * @param tag
     * @param attr
     */
    @Deprecated
    public static List<String> queryHtmlAttr(String html, String tag, String attr) {
    	List<String> res = null;
    	Pattern p = Pattern.compile("(?i)<" + tag + ".+?>");
		Matcher m = p.matcher(html);
		while(m.find()) {
			String findStr = m.group(0);
			String attrStr = RegexUtils.regex(findStr, "(?i)(?<=" + tag + "=[\"|']).+?(?=[\"|'])");
			if(StringUtils.isNotBlank(attrStr)) {
				if(res == null) {
					res = new ArrayList<String>();
				}
				res.add(attrStr);
			}
		}
		return res;
    }
    
    /**
     * 分割字符串为List
     * 
     * @param str
     * @param separator
     * @param limit
     * @param generic
     * @return
     */
    public static <E> List<E> splitToList(String str, String separator, Integer limit, Class<E> generic) {
    	List<E> list = new ArrayList<E>();
    	if(isNotBlank(str)) {
    		String[] strs = null;
        	if(limit != null) {
        		strs = str.split(separator, limit);
        	} else {
        		strs = str.split(separator);
        	}
        	if(ArrayUtils.isNotBlank(strs)) {
        		for(String strBuf: strs) {
            		list.add(ObjectUtils.build(generic, strBuf));
            	}
        	}
    	}
    	return list;
    }
    
    public static <E> List<E> splitToList(String str, String separator, Class<E> generic) {
    	return splitToList(str, separator, null, generic);
    }
    
    public static String trim(String str) {
    	if(str != null) {
    		return str.replaceAll("^[ |　| | ]+", "").replaceAll("[ |　| | ]+$", "");
    	}
		return str;
	}
    
    /**
     * 去除html标签
     * 
     * @param content 需要去除html标签的String内容
     * @return
     */
    public static String trimHtmlTag(String content) {
    	if(isBlank(content)){
    		return content;
    	}
    	return content.replaceAll("<[^>]+>","").replaceAll("&nbsp;","").replaceAll("\\s*|\\t|\\r|\\n", "");
    }
    
    /**
     * 去除html属性
     * 
     * @param content
     * @return
     */
    public static String trimHtmlAttr(String content) {
    	return trimHtmlAttrBase(content, null, TRIM_HTML_ATTR_COMMEND);
    }
    
    /**
     * 去除html属性,排除相应的
     * 
     * @param content
     * @param exclude
     * @return
     */
    public static String trimHtmlAttrWithExclude(String content, String...exclude) {
    	return trimHtmlAttrBase(content, exclude, TRIM_HTML_ATTR_WITH_EXCLUDE_COMMEND);
    }
    
    /**
     * 去除html属性,只去掉相应的
     * 
     * @param content
     * @param include
     * @return
     */
    public static String trimHtmlAttrWithInclude(String content, String...include) {
    	return trimHtmlAttrBase(content, include, TRIM_HTML_ATTR_WITH_INCLUDE_COMMEND);
    }
    
    private static String trimHtmlAttrBase(String content, String[] strs, int commend) {
    	if(StringUtils.isBlank(content)) {
    		return content;
    	}
    	content = content.replaceAll("[\\t|\\r|\\n]", "");
    	// 过滤带""attr
    	content = trimHtmlAttrBase(content, strs, commend, "(?i)\\s+?([^=]+)=[\"|'].*?[\"|']");
    	// 过滤无""attr
    	return trimHtmlAttrBase(content, strs, commend, "(?i)\\s+?([^=]+)=.+?(?=[\\s|>])").replaceAll("\\s+", " ");
    }
    
    private static String trimHtmlAttrBase(String content, String[] strs, int commend, String regex) {
    	Pattern pattern = Pattern.compile("<(?!/).+?>"); 
    	Matcher matcher = pattern.matcher(content);
    	StringBuffer sb = new StringBuffer();
    	int offset = 0;
    	while(matcher.find()) {
    		String replace = matcher.group(0);
    		Pattern p = Pattern.compile(regex);
    		Matcher childMatcher = p.matcher(replace);
    		StringBuffer childSb = new StringBuffer();
    		int childOffset = 0;
    		while(childMatcher.find()) {
    			switch (commend) {
				case TRIM_HTML_ATTR_WITH_EXCLUDE_COMMEND:
					if(ArrayUtils.isNotBlank(strs) && contains(childMatcher.group(1).trim(), strs, true)) {
	    				continue;
	    			}
					break;
				case TRIM_HTML_ATTR_WITH_INCLUDE_COMMEND:
					if(ArrayUtils.isBlank(strs) || !contains(childMatcher.group(1).trim(), strs, true)) {
	    				continue;
	    			}
					break;
				}
    			childSb.append(substring(replace, childOffset, childMatcher.start()) + " ");
    			childOffset = childMatcher.end();
    		}
    		childSb.append(substring(replace, childOffset));
    		sb.append(substring(content, offset, matcher.start()) + childSb.toString());
    		offset = matcher.end();
    	}
    	sb.append(substring(content, offset));
    	return sb.toString();
    }
    
    /**
     * 半角转全角
     * 
     * @param input
     * @return
     */
	public static String toSbc(String input) {
		char c[] = input.toCharArray();
		for (int i = 0; i < c.length; i++) {
			if (c[i] == ' ') {
				c[i] = '\u3000';
			} else if (c[i] < '\177') {
				c[i] = (char) (c[i] + 65248);

			}
		}
		return new String(c);
	}
	
	/**
	 * 全角转半角
	 * 
	 * @param input
	 * @return
	 */
	public static String toDbc(String input) {
		char c[] = input.toCharArray();
		for (int i = 0; i < c.length; i++) {
			if (c[i] == '\u3000') {
				c[i] = ' ';
			} else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
				c[i] = (char) (c[i] - 65248);

			}
		}
		String returnString = new String(c);
		return returnString;
	}
	
	/**
	 * 保留小数(采用字符串截取)
	 * 
	 * @param str
	 * @param count 保留位数
	 * @return
	 */
	public static String keepDecimalPlaces(String str, int count) {
		return RegexUtils.regex(str, "\\d+(\\.\\d{" + count + "}(?=\\d+)){0,1}");
	}
	
	/**
	 * 文本分行
	 * 
	 * @param str
	 * @return
	 */
	public static String[] splitLine(String str) {
		String[] lines = null;
		if(str != null) {
			lines = str.split("\r\n|\\n|\\r", -1);
		}
		return lines;
	}
	
	/**
	 * 文本分行
	 * 
	 * @param str
	 * @return
	 */
	public static List<String> splitLineToList(String str) {
		String[] lines = splitLine(str);
		return ArrayUtils.toList(lines);
	}
	
	/**
	 * 首字母小写
	 * 
	 * @param str
	 * @return
	 */
	public static String lowerFirst(String str) {
		if(isNotBlank(str)) {
			str = Character.toLowerCase(str.charAt(0)) + str.substring(1);
		}
        return str;
    }
	
	/**
	 * 小写的下划线命名
	 * 
	 * @param str
	 * @return
	 */
	public static String toLowerUnderlineCase(String str) {
		if(StringUtils.isNotBlank(str)) {
			str = camelCaseToUnderlineCase(toLowerCamelCase(str));
		}
		return str;
	}
	
	/**
	 * 首字母小写的驼峰命名
	 * 
	 * @param str
	 * @return
	 */
	public static String toLowerCamelCase(String str) {
		if(StringUtils.isNotBlank(str)) {
			str = underlineCaseToCamelCase(str.replaceAll("^_", "").replaceAll("_$", ""));
			str = lowerFirst(str);
		}
		return str;
	}
	
	// 驼峰转下划线命名
	private static String camelCaseToUnderlineCase(String str) {
		if(StringUtils.isNotBlank(str)) {
			int len = str.length();
	        StringBuilder sb = new StringBuilder(len);
	        for (int i = 0; i < len; i++) {
	            char c = str.charAt(i);    
	            if (Character.isUpperCase(c)){
	                sb.append(UNDERLINE);    
	                sb.append(Character.toLowerCase(c));
	            }else{
	                sb.append(c);    
	            }
	        }
	        return sb.toString();
		}
        return str;
	}
	
	// 下划线转驼峰命名
	private static String underlineCaseToCamelCase(String str) {
		if(StringUtils.isNotBlank(str)) {
			int len = str.length();
	        StringBuilder sb = new StringBuilder(len); 
	        boolean up = false;
	        for (int i = 0; i < len; i++) {    
	            char c = str.charAt(i);    
	            if (UNDERLINE.equals(c + "")){ 
	            	up = true;
	            	continue;
	            }else{
	            	if(up) {
	            		sb.append((c + "").toUpperCase());
	            		up = false;
	            	} else {
	            		sb.append(c);   
	            	}
	            }
	        }    
	        return sb.toString();
		}
        return str;
	}
	
}
